home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / pnl003.zip / SORTUNIT.PAS < prev    next >
Pascal/Delphi Source File  |  1990-07-06  |  9KB  |  291 lines

  1. unit SortUnit;
  2.  
  3. { This unit contains all the sort routines for the 'All Sorts of Sorts'
  4.   article in PNL003. The code is copyrighted by Pete Davis. This code may
  5.   be distributed only in un-modified form and only accompanying the Pascal
  6.   NewsLetter Issue #3.                                                     }
  7.  
  8. interface
  9.  
  10. const
  11.   MaxSize = 1000;       { Maximum size of an Array                  }
  12.  
  13. type
  14.   DataType = integer;   { Need to give our routine a data-type      }
  15.   DatArray = array[1..MaxSize] of DataType;  { Our data array       }
  16.  
  17. procedure Bubble_Sort(Var List : DatArray; NumItems : integer);
  18. procedure Select_Sort(Var List : DatArray; NumItems : integer);
  19. procedure Insert_Sort(Var List : DatArray; NumItems : integer);
  20. procedure Shell_Sort(Var List : DatArray; NumItems : integer);
  21. procedure Merge_Sort(Var List : DatArray; Start, NumItems : integer);
  22. procedure Quick_Sort(Var List : DatArray; Start, List_End : integer);
  23.  
  24.  
  25. implementation
  26.  
  27. procedure exchange(Var Item1, Item2 : DataType);
  28.  
  29. { This procedure will exchange Item1 with Item2. This procedure
  30.   is local to this unit as it is used by many of the sort programs. }
  31.  
  32. var
  33.   Temp: DataType;
  34.  
  35. begin
  36.   Temp := Item1;
  37.   Item1 := Item2;      { Switch Item1 and Item2 using Temp }
  38.   Item2 := Temp;
  39. end;
  40.  
  41.  
  42. procedure Bubble_Sort(Var List : DatArray; NumItems : integer);
  43.  
  44. { This procedure is the actual Bubble-sort. List is the array of
  45.   data of type DataType. NumItems is the number of items in List. }
  46.  
  47. var
  48.   Done  : boolean; { Find out when we are finished sorting! }
  49.   Index : integer; { Use this as our Index into the array   }
  50.  
  51. begin
  52.   Done := False;
  53.   while not Done do
  54.     begin
  55.       Done := True;  { reset done to true }
  56.  
  57.       for Index := 1 to (NumItems - 1) do            { Go through the list }
  58.         begin
  59.           if List[Index] > List[Index + 1] then      { compare neighbors   }
  60.             begin
  61.               Exchange(List[Index], List[Index + 1]); { had to exchange one,}
  62.               Done := False;                         { so not done yet!    }
  63.             end; { if }
  64.         end; { for }
  65.     end; { while }
  66. end; { Bubble_Sort }
  67.  
  68.  
  69. procedure Select_Sort(Var List : DatArray; NumItems : integer);
  70.  
  71. { This is the Selection Sort procedure. Parameters are the same as
  72.   Bubble_Sort. To show the simplicity, I use only 4 lines of very
  73.   straight-foward code. An alternate, and quicker method is to have
  74.   a variable that checks whether or not an exchange was made in a
  75.   given pass throught the inner loop. If an exchange was not made then
  76.   the list is in order. This would keep the sort from trying to work on
  77.   a list that is already in order.                                       }
  78.  
  79. var
  80.   Inner_Loop,                { Pretty self explanitory. The inner }
  81.   Outer_Loop  : integer;     { and outer indices into the arrays.}
  82.  
  83. begin
  84.   for Outer_Loop := 1 to NumItems - 1 do
  85.     for Inner_Loop := Outer_Loop + 1 to NumItems do
  86.       if List[Inner_Loop] < List[Outer_Loop] then
  87.         exchange(List[Inner_Loop], List[Outer_Loop]);
  88. end;
  89.  
  90.  
  91. procedure Insert_Sort(Var List : DatArray; NumItems : integer);
  92.  
  93. { This is the Insertion Sort. This is a rather in-efficient version,
  94.   as it uses an array. The problem is that the procedure Shift must
  95.   move large portions of data in the list. This is much quicker in a
  96.   linked-list implementation of the sort as the data isn't actually
  97.   shifted in memory, only a couple links need to be changed.         }
  98.  
  99. var
  100.   Cur,                     { Current position in array     }
  101.   Index     : integer;     { Secondary index into array    }
  102.   CurVal    : DataType;    { Value of item in Cur Position }
  103.  
  104.  
  105. begin
  106.   for Cur := 2 to NumItems do
  107.     begin
  108.       CurVal := List[Cur];
  109.       Index := Cur - 1;
  110.  
  111.       { Start from the end and go to the beginning }
  112.       while (Index > 0) and (CurVal < List[Index]) do
  113.         begin
  114.           { Move everything over to insert CurVal }
  115.           List[Index + 1] := List[Index];
  116.           dec(Index);
  117.         end;
  118.       List[Index+1] := CurVal;
  119.     end;
  120. end;
  121.  
  122.  
  123. procedure Shell_Sort(Var List : DatArray; NumItems : integer);
  124.  
  125. { This is the shell sort. It is much like the bubble sort, except
  126.   instead of comparing and swapping adjacent elements, it is done
  127.   over a distance of GAP.                                         }
  128.  
  129. var
  130.   Index,                   { This is our index into the array }
  131.   gap     : integer;       { This is the gap of the sort.     }
  132.   done    : boolean;
  133.  
  134. begin
  135.   gap := NumItems;
  136.   while gap <> 1 do
  137.     begin
  138.       gap := gap div 2;    { Set our Gap to half of what it was }
  139.       done := false;
  140.       while not done do
  141.         begin
  142.           done := true;    { Set done to true }
  143.           for Index := 1 to NumItems - Gap do
  144.             if List[Index] > List[Index + Gap] then
  145.               begin
  146.                 exchange(List[Index], List[Index + Gap]);
  147.                 done := false;  { If an exchange was made, we're not done. }
  148.               end;
  149.         end;
  150.     end;
  151. end;
  152.  
  153.  
  154.  
  155. procedure Merge_Sort(Var List : DatArray; Start, NumItems : integer);
  156.  
  157. { This is the recursive Merge Sort. It starts by dividing the list
  158.   in half, recursively taking care of both sides of the list. Then it
  159.   puts the pieces back in the correct order in the Merge_List procedure. }
  160.  
  161.  
  162.   procedure Merge_List(Var List : DatArray; Start, Mid, NumItems : integer);
  163.  
  164.   var
  165.     Copy     : DatArray;     { This is where the results of the sort go }
  166.     Left,                    { Left side of a half-list                 }
  167.     Right,                   { Right side of of a half-list             }
  168.     Index    : integer;      { Index into array.                        }
  169.  
  170.  
  171.   begin
  172.     Index := Start;
  173.     Left  := Start;
  174.     Right := Mid + 1;
  175.  
  176.     { Merge the half-lists }
  177.     while (mid >= left) and (NumItems >= Right) do
  178.       if List[Left] < List[Right] then
  179.         begin
  180.           Copy[Index] := List[Left];
  181.           inc(Index); inc(Left);
  182.         end
  183.       else
  184.         begin
  185.           Copy[Index] := List[Right];
  186.           inc(Index); inc(Right);
  187.         end;
  188.  
  189.     { Take care of the left side }
  190.     while Mid >= Left do
  191.       begin
  192.         Copy[Index] := List[Left];
  193.         inc(Index); inc(Left);
  194.       end;
  195.  
  196.     { Take care of the right side }
  197.     while NumItems >= Right do
  198.       begin
  199.         Copy[Index] := List[Right];
  200.         inc(Index); inc(Right);
  201.       end;
  202.     for Index := Start to NumItems do
  203.       List[Index] := Copy[Index];
  204.   end;
  205.  
  206.  
  207. var
  208.   Mid     : integer;
  209.  
  210. begin
  211.   if Start < NumItems then
  212.     begin
  213.       Mid := (Start + NumItems) div 2;
  214.       Merge_Sort(List, Start, Mid);
  215.       Merge_Sort(List, Mid+1, NumItems);
  216.       Merge_List(List, Start, Mid, NumItems);
  217.     end;
  218. end;
  219.  
  220.  
  221.  
  222. procedure Quick_Sort(Var List : DatArray; Start, List_End : integer);
  223.  
  224. { This is the Quick_Sort Procedure. Like the Merge_Sort procedure
  225.   it is recursive. First a pivot point is picked. Then the
  226.   individual sides are sorted.                                     }
  227.  
  228.  
  229.  
  230.   procedure Split(Var List : DatArray; Start, List_End : integer;
  231.                   Var PivotIndex : integer);
  232.  
  233.   { Move values less than pivot to the left of pivot and move
  234.     values greater than pivot to the right.                        }
  235.  
  236.   var
  237.     Pivot,
  238.     LeftPointer,              { Pointers on the left and right side }
  239.     RightPointer : integer;   { of the pivot point.                 }
  240.  
  241.   begin
  242.     PivotIndex := (Start+List_End) div 2;
  243.     Pivot := List[PivotIndex]; { Take middle item as pivot value }
  244.  
  245.     { Set the left and right pointers for moving through the Array. }
  246.     LeftPointer := Start;
  247.     RightPointer := List_End;
  248.  
  249.     repeat
  250.       { Find all values on the wrong side of the pivot value
  251.         and move them to the correct side.                   }
  252.  
  253.  
  254.       { Start from the left and go towards the right }
  255.       while (List[LeftPointer] <= Pivot) and
  256.             (LeftPointer < List_End) do inc(LeftPointer);
  257.  
  258.       { Start from the right and go towards the left }
  259.       while (List[RightPointer] > Pivot) and
  260.             (RightPointer > Start) do dec(RightPointer);
  261.  
  262.       { If they're on the wrong side, then switch them }
  263.       if LeftPointer < RightPointer then
  264.           Exchange(List[LeftPointer], List[RightPointer]);
  265.     until(LeftPointer >= RightPointer);
  266.  
  267.  
  268.     { Put our Pivot into the correct location now. }
  269.     exchange(List[PivotIndex], List[RightPointer]);
  270.     PivotIndex := RightPointer;
  271.   end;
  272.  
  273.  
  274. var
  275.   PivotIndex : integer;
  276.  
  277. begin
  278.   if Start < List_End then
  279.     begin
  280.       { Split the table into to halves. }
  281.       Split(List, Start, List_End, PivotIndex);
  282.  
  283.       { Take care of the left side. }
  284.       Quick_Sort(List, Start, PivotIndex);
  285.  
  286.       { Now the right side.}
  287.       Quick_Sort(List, PivotIndex+1, List_End);
  288.     end;
  289. end;
  290.  
  291. end. {End of unit}